14#!/bin/bash

# CPU调度优化脚本
# 作者: Craft
# 日期: 2025/9/1
# 描述: 此脚本通过监控CPU频率动态调整CPU频率，避免长时间睿频导致的系统不稳定
# 用法: sudo ./cpu_scheduler.sh [选项]

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 默认参数
CHECK_INTERVAL=5           # 默认检查间隔为5秒
HIGH_FREQ_THRESHOLD=80      # 高频率阈值百分比
LOW_FREQ_THRESHOLD=30       # 低频率阈值百分比
SUSTAINED_PERIOD_HIGH=10    # 高负载持续时间阈值（秒）
SUSTAINED_PERIOD_LOW=60     # 低负载持续时间阈值（秒）
FREQ_REDUCTION=25           # 频率降低幅度（百分比）
FREQ_INCREASE=25            # 频率增加幅度（百分比）
TARGET_FREQ_AFTER_REDUCTION=75  # 降频后的目标频率百分比
IO_CRITICAL_THRESHOLD=90    # 极端IO负载阈值
IO_SEVERE_THRESHOLD=80      # 严重IO负载阈值
IO_HIGH_THRESHOLD=70        # 高IO负载阈值
LOG_FILE="/var/log/cpu-scheduler.log"
MAX_LOG_SIZE_MB=5           # 最大日志文件大小(MB)
MAX_LOG_FILES=5             # 保留的日志文件数量

# 全局变量
CURRENT_STATE="normal"      # normal, high, low
HIGH_FREQ_START=0           # 高频率开始时间
LOW_FREQ_START=0            # 低频率开始时间
LAST_LOG_TIME=0             # 上次记录日志的时间

# 全局变量用于存储上一次的磁盘IO统计数据
LAST_READ_SECTORS=0
LAST_WRITE_SECTORS=0
LAST_IO_TIME=0

# 配置文件路径
CONFIG_FILE="$(dirname "$(readlink -f "$0")")/cpu-scheduler.conf"

# 显示帮助信息
show_help() {
    echo -e "${BLUE}CPU调度优化脚本 - 动态调整CPU频率以避免长时间睿频导致的系统不稳定${NC}"
    echo
    echo -e "${GREEN}基本用法:${NC}"
    echo "  $0 [选项]"
    echo
    echo -e "${GREEN}服务管理命令:${NC}"
    echo "  $0 --help                    显示此帮助信息"
    echo "  $0 --service                 以服务模式运行"
    echo "  $0 --temp-config [参数]      临时修改参数(仅本次启动有效)"
    echo
    echo -e "${GREEN}监控参数选项:${NC}"
    echo "  -i, --interval <秒>        检查间隔，默认5秒"
    echo "  -h, --high-threshold <百分比> 高频率阈值，默认80%"
    echo "  -l, --low-threshold <百分比>  低频率阈值，默认30%"
    echo "  -s, --sustained <秒>       高负载持续时间阈值，默认10秒"
    echo "  --sustained-low <秒>       低负载持续时间阈值，默认60秒"
    echo
    echo -e "${GREEN}频率调整选项:${NC}"
    echo "  -r, --reduction <百分比>   频率降低幅度，默认25%"
    echo "  -n, --increase <百分比>    频率增加幅度，默认25%"
    echo
    echo -e "${GREEN}IO监控选项:${NC}"
    echo "  IO_CRITICAL_THRESHOLD=90    # 极端IO负载阈值"
    echo "  IO_SEVERE_THRESHOLD=80     # 严重IO负载阈值"
    echo "  IO_HIGH_THRESHOLD=70        # 高IO负载阈值"
    echo "  SATA_READ_THRESHOLD=10000   # SATA 4K读阈值(kB/s)"
    echo "  SATA_WRITE_THRESHOLD=8000  # SATA 4K写阈值(kB/s)"
    echo "  NVME_READ_THRESHOLD=40000  # NVMe 4K读阈值(kB/s)"
    echo "  NVME_WRITE_THRESHOLD=36000 # NVMe 4K写阈值(kB/s)"
    echo
    echo -e "${GREEN}其他选项:${NC}"
    echo "  -f, --log-file <文件>      日志文件路径，默认/var/log/cpu-scheduler.log"
    echo
    echo -e "${YELLOW}服务运行时动态调整参数:${NC}"
    echo "  sudo systemctl reload cpu-scheduler.service [参数]"
    echo "  例如: sudo systemctl reload cpu-scheduler.service interval=3 high=85"
    echo
    echo -e "${GREEN}示例:${NC}"
    echo "  $0 -i 5 -h 80 -l 30 -s 10 --sustained-low 60"
    echo "  $0 -r 25 -n 25"
    echo "  $0 --temp-config interval=3 high=85 low=35"
    echo
    echo -e "${YELLOW}更多详细信息请参考README.md文件${NC}"
}

# 读取配置文件
load_config() {
    if [ -f "$CONFIG_FILE" ]; then
        echo -e "${GREEN}正在加载配置文件: $CONFIG_FILE${NC}"
        source "$CONFIG_FILE"
        echo -e "${GREEN}配置文件加载完毕，当前配置内容如下:${NC}"
        echo -e "${BLUE}=========================================${NC}"
        echo -e "${YELLOW}# 监控设置${NC}"
        echo -e "${YELLOW}CHECK_INTERVAL=${CHECK_INTERVAL}           # 检查间隔(秒)${NC}"
        echo -e "${YELLOW}HIGH_FREQ_THRESHOLD=${HIGH_FREQ_THRESHOLD}     # 高频率阈值(%)${NC}"
        echo -e "${YELLOW}LOW_FREQ_THRESHOLD=${LOW_FREQ_THRESHOLD}      # 低频率阈值(%)${NC}"
        echo -e "${YELLOW}SUSTAINED_PERIOD_HIGH=${SUSTAINED_PERIOD_HIGH}   # 高负载持续时间(秒)${NC}"
        echo -e "${YELLOW}SUSTAINED_PERIOD_LOW=${SUSTAINED_PERIOD_LOW}    # 低负载持续时间(秒)${NC}"
        echo
        echo -e "${YELLOW}# 频率调整${NC}"
        echo -e "${YELLOW}FREQ_REDUCTION=${FREQ_REDUCTION}          # 降频幅度(%)${NC}"
        echo -e "${YELLOW}FREQ_INCREASE=${FREQ_INCREASE}           # 升频幅度(%)${NC}"
        echo -e "${YELLOW}TARGET_FREQ_AFTER_REDUCTION=${TARGET_FREQ_AFTER_REDUCTION}  # 降频后目标频率(%)${NC}"
        echo
        echo -e "${YELLOW}# IO负载阈值${NC}"
        echo -e "${YELLOW}IO_CRITICAL_THRESHOLD=${IO_CRITICAL_THRESHOLD}   # 极端IO负载(%)${NC}"
        echo -e "${YELLOW}IO_SEVERE_THRESHOLD=${IO_SEVERE_THRESHOLD}     # 严重IO负载(%)${NC}"
        echo -e "${YELLOW}IO_HIGH_THRESHOLD=${IO_HIGH_THRESHOLD}       # 高IO负载(%)${NC}"
        echo
        echo -e "${YELLOW}# 日志设置${NC}"
        echo -e "${YELLOW}LOG_FILE=${LOG_FILE}${NC}"
        echo -e "${YELLOW}MAX_LOG_SIZE_MB=${MAX_LOG_SIZE_MB}          # 最大日志大小(MB)${NC}"
        echo -e "${YELLOW}MAX_LOG_FILES=${MAX_LOG_FILES}            # 保留日志文件数${NC}"
        echo -e "${BLUE}=========================================${NC}"
        echo
    else
        echo -e "${YELLOW}未找到配置文件，使用默认配置${NC}"
    fi
}

# 解析命令行参数
while [[ $# -gt 0 ]]; do
    case $1 in
        -i|--interval)
            CHECK_INTERVAL="$2"
            shift 2
            ;;
        -h|--high-threshold)
            HIGH_FREQ_THRESHOLD="$2"
            shift 2
            ;;
        -l|--low-threshold)
            LOW_FREQ_THRESHOLD="$2"
            shift 2
            ;;
        -s|--sustained)
            SUSTAINED_PERIOD_HIGH="$2"
            shift 2
            ;;
        --sustained-low)
            SUSTAINED_PERIOD_LOW="$2"
            shift 2
            ;;
        -r|--reduction)
            FREQ_REDUCTION="$2"
            shift 2
            ;;
        -n|--increase)
            FREQ_INCREASE="$2"
            shift 2
            ;;
        -f|--log-file)
            LOG_FILE="$2"
            shift 2
            ;;
        --service)
            SERVICE_MODE=1
            shift
            ;;
        --temp-config)
            echo -e "${YELLOW}临时修改配置参数 (仅本次启动有效):${NC}"
            shift
            while [[ "$1" != --* && "$1" != "" ]]; do
                case "$1" in
                    interval=*)
                        CHECK_INTERVAL="${1#*=}"
                        echo "  检查间隔: ${CHECK_INTERVAL}秒"
                        ;;
                    high=*)
                        HIGH_FREQ_THRESHOLD="${1#*=}"
                        echo "  高频率阈值: ${HIGH_FREQ_THRESHOLD}%"
                        ;;
                    low=*)
                        LOW_FREQ_THRESHOLD="${1#*=}"
                        echo "  低频率阈值: ${LOW_FREQ_THRESHOLD}%"
                        ;;
                    sustained-high=*)
                        SUSTAINED_PERIOD_HIGH="${1#*=}"
                        echo "  高负载持续时间: ${SUSTAINED_PERIOD_HIGH}秒"
                        ;;
                    sustained-low=*)
                        SUSTAINED_PERIOD_LOW="${1#*=}"
                        echo "  低负载持续时间: ${SUSTAINED_PERIOD_LOW}秒"
                        ;;
                    reduction=*)
                        FREQ_REDUCTION="${1#*=}"
                        echo "  降频幅度: ${FREQ_REDUCTION}%"
                        ;;
                    increase=*)
                        FREQ_INCREASE="${1#*=}"
                        echo "  升频幅度: ${FREQ_INCREASE}%"
                        ;;
                    *)
                        echo -e "${RED}未知参数: $1${NC}"
                        ;;
                esac
                shift
            done
            ;;
        --help)
            show_help
            exit 0
            ;;
        *)
            echo -e "${RED}未知选项: $1${NC}"
            show_help
            exit 1
            ;;
    esac
done

# 确保变量有默认值
SUSTAINED_PERIOD_HIGH=${SUSTAINED_PERIOD_HIGH:-10}
SUSTAINED_PERIOD_LOW=${SUSTAINED_PERIOD_LOW:-30}

# 检查依赖
check_dependencies() {
    if ! command -v iostat &> /dev/null; then
        echo -e "${YELLOW}检测到缺少iostat命令，尝试安装sysstat包...${NC}"
        if command -v apt-get &> /dev/null; then
            apt-get update && apt-get install -y sysstat
        elif command -v yum &> /dev/null; then
            yum install -y sysstat
        else
            echo -e "${RED}无法自动安装sysstat，请手动安装:${NC}"
            echo "Debian/Ubuntu: sudo apt install sysstat"
            echo "RHEL/CentOS: sudo yum install sysstat"
            exit 1
        fi
    fi
}

# 检查是否以root权限运行
check_root() {
    if [[ $EUID -ne 0 ]]; then
        echo -e "${RED}此脚本需要root权限运行${NC}"
        echo "请使用 sudo $0 重新运行"
        exit 1
    fi
    check_dependencies
}

# 日志轮转检查
check_log_rotation() {
    local max_size_mb=10  # 最大日志大小(MB)
    local max_files=5     # 保留的日志文件数量
    
    # 检查日志文件是否存在且超过大小限制
    if [ -f "$LOG_FILE" ] && [ $(du -m "$LOG_FILE" | cut -f1) -gt $max_size_mb ]; then
        # 轮转日志文件
        for i in $(seq $((max_files-1)) -1 1); do
            [ -f "${LOG_FILE}.${i}" ] && mv "${LOG_FILE}.${i}" "${LOG_FILE}.$((i+1))"
        done
        mv "$LOG_FILE" "${LOG_FILE}.1"
        echo -e "[$(date "+%Y-%m-%d %H:%M:%S")] [INFO] 日志文件已轮转" > "$LOG_FILE"
    fi
}

# 日志函数
log_message() {
    local level="$1"
    local message="$2"
    local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
    
    # 检查日志轮转
    check_log_rotation
    
    # 添加系统状态信息到日志
    if [[ "$level" == "CRITICAL" || "$level" == "ERROR" ]]; then
        local sysinfo=$(top -bn1 | head -5)
        local meminfo=$(free -h)
        local iostat=$(iostat -d -y 1 1)
        message="$message\n系统状态:\n$sysinfo\n内存使用:\n$meminfo\nIO状态:\n$iostat"
    fi
    
    echo -e "[$timestamp] [$level] $message" >> "$LOG_FILE"
    
    # 如果不是服务模式，也输出到控制台
    if [[ $SERVICE_MODE -ne 1 ]]; then
        case "$level" in
            INFO)
                echo -e "${BLUE}[$timestamp] [$level] $message${NC}"
                ;;
            WARNING)
                echo -e "${YELLOW}[$timestamp] [$level] $message${NC}"
                ;;
            ERROR|CRITICAL)
                echo -e "${RED}[$timestamp] [$level] $message${NC}"
                ;;
            SUCCESS)
                echo -e "${GREEN}[$timestamp] [$level] $message${NC}"
                ;;
            *)
                echo -e "[$timestamp] [$level] $message"
                ;;
        esac
    fi
}

# 获取当前系统负载（百分比）
get_system_load() {
    # 使用top命令获取1分钟平均负载并转换为百分比
    local load_avg=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | sed 's/,//')
    local cpu_count=$(nproc)
    local load_percent=0
    
    # 检查load_avg是否为有效数字
    if [[ -n "$load_avg" && "$load_avg" =~ ^[0-9.]+$ ]]; then
        load_percent=$(echo "$load_avg * 100 / $cpu_count" | bc -l 2>/dev/null | awk '{printf "%.0f", $0}' || echo 0)
    fi
    
    echo "$load_percent"
}

# 获取详细的IO负载信息
get_io_load() {
    local retries=3
    
    while [ $retries -gt 0 ]; do
        # 获取设备类型和详细IO统计
        io_stats=$(iostat -d -k -x -y 1 1)
        
        if [ -n "$io_stats" ]; then
            # 提取设备名和统计信息
            local devices=$(echo "$io_stats" | awk 'NR>3 && $0 !~ /^$/ {print $1}' | sort | uniq)
            local result=""
            
            # 同时计算总的读写速度用于日志显示
            local total_rkB=0
            local total_wkB=0
            
            for device in $devices; do
                # 检测设备类型
                local device_type="Unknown"
                if [[ $device == nvme* ]]; then
                    device_type="NVMe"
                elif [[ $device == sd* ]] || [[ $device == hd* ]]; then
                    device_type="SATA"
                fi
                
                # 提取该设备的详细IO统计
                local dev_stats=$(echo "$io_stats" | grep "^$device ")
                if [ -n "$dev_stats" ]; then
                    # 根据iostat -d -k -x -y输出格式正确解析字段
                    # 字段顺序: Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s wrqm/s %wrqm w_await wareq-sz d/s dkB/s drqm/s %drqm d_await dareq-sz f/s f_await aqu-sz %util
                    local util=$(echo "$dev_stats" | awk '{print $NF}')   # %util是最后一列
                    local rkB=$(echo "$dev_stats" | awk '{print $6}')     # rkB/s是第6列
                    local wkB=$(echo "$dev_stats" | awk '{print $7}')     # wkB/s是第7列
                    local rrqm=$(echo "$dev_stats" | awk '{print $2}')    # rrqm/s是第2列
                    local wrqm=$(echo "$dev_stats" | awk '{print $3}')    # wrqm/s是第3列
                    local r_await=$(echo "$dev_stats" | awk '{print $10}') # r_await是第10列
                    local w_await=$(echo "$dev_stats" | awk '{print $11}') # w_await是第11列
                    
                    # 累加总读写速度用于日志显示
                    total_rkB=$(echo "$total_rkB $rkB" | awk '{print $1 + $2}')
                    total_wkB=$(echo "$total_wkB $wkB" | awk '{print $1 + $2}')
                    
                    # 构建结果字符串
                    result+="$device_type:$device:util=$util,rkB=$rkB,wkB=$wkB,rrqm=$rrqm,wrqm=$wrqm,r_await=$r_await,w_await=$w_await;"
                fi
            done
            
            # 添加总读写速度信息用于日志显示
            result+="read_speed_kbs=$total_rkB,write_speed_kbs=$total_wkB"
            
            echo "$result"
            return
        fi
        
        sleep 0.5
        ((retries--))
    done
    
    # 如果所有重试都失败，返回空并记录错误
    log_message "ERROR" "无法获取有效的IO负载数据"
    echo ""
}

# 获取CPU信息
get_cpu_info() {
    # 检查CPU频率调节器是否可用
    if [ ! -d "/sys/devices/system/cpu/cpu0/cpufreq" ]; then
        log_message "ERROR" "系统不支持CPU频率调节"
        exit 1
    fi
    
    # 获取CPU核心数
    CPU_CORES=$(nproc)
    log_message "INFO" "检测到 ${CPU_CORES} 个CPU核心"
}

# 获取当前CPU频率（百分比）
# 修改为返回任意CPU核心中的最高频率，而非平均频率
get_cpu_frequency() {
    local max_freq=0
    
    # 遍历所有CPU核心获取频率
    for cpu_dir in /sys/devices/system/cpu/cpu[0-9]*; do
        if [ -d "$cpu_dir/cpufreq" ]; then
            # 获取当前实际频率
            if [ -f "$cpu_dir/cpufreq/scaling_cur_freq" ] && [ -f "$cpu_dir/cpufreq/cpuinfo_max_freq" ]; then
                CURRENT_FREQ=$(cat "$cpu_dir/cpufreq/scaling_cur_freq")
                HW_MAX_FREQ=$(cat "$cpu_dir/cpufreq/cpuinfo_max_freq")
                
                # 计算当前核心频率百分比
                if [ "$HW_MAX_FREQ" -ne 0 ]; then
                    CORE_PERCENT=$(echo "$CURRENT_FREQ * 100 / $HW_MAX_FREQ" | bc -l 2>/dev/null | awk '{printf "%.0f", $0}' || echo 0)
                    # 更新最大频率
                    if [ "$CORE_PERCENT" -gt "$max_freq" ]; then
                        max_freq=$CORE_PERCENT
                    fi
                fi
            fi
        fi
    done
    
    # 返回最高核心频率百分比
    echo "$max_freq"
}

# 获取当前CPU频率设置
get_current_cpu_freq() {
    local cpu=0
    CPU_DIR="/sys/devices/system/cpu/cpu$cpu/cpufreq"
    
    if [ -d "$CPU_DIR" ]; then
        # 获取当前最大频率
        if [ -f "${CPU_DIR}/scaling_max_freq" ]; then
            CURRENT_MAX_FREQ=$(cat ${CPU_DIR}/scaling_max_freq)
        else
            CURRENT_MAX_FREQ=0
        fi
        
        # 获取硬件最大频率
        if [ -f "${CPU_DIR}/cpuinfo_max_freq" ]; then
            HW_MAX_FREQ=$(cat ${CPU_DIR}/cpuinfo_max_freq)
        else
            HW_MAX_FREQ=0
        fi
        
        # 计算当前频率百分比
        if [ "$HW_MAX_FREQ" -ne 0 ]; then
            CURRENT_PERCENT=$(echo "$CURRENT_MAX_FREQ * 100 / $HW_MAX_FREQ" | bc -l 2>/dev/null | awk '{printf "%.0f", $0}' || echo 0)
        else
            CURRENT_PERCENT=0
        fi
    else
        log_message "ERROR" "CPU $cpu 不支持频率调节"
        CURRENT_PERCENT=0
        CURRENT_MAX_FREQ=0
        HW_MAX_FREQ=0
    fi
}

# 设置CPU最大频率（以硬件最大频率的百分比表示）
set_cpu_max_freq() {
    local target_percent=$1
    
    # 确保target_percent是有效的数字
    if ! [[ "$target_percent" =~ ^[0-9]+$ ]]; then
        log_message "ERROR" "无效的目标频率百分比: $target_percent"
        return 1
    fi
    
    log_message "INFO" "开始设置CPU最大频率到 ${target_percent}%"
    
    for ((i=0; i<${CPU_CORES}; i++)); do
        CPU_DIR="/sys/devices/system/cpu/cpu$i/cpufreq"
        
        if [ -d "$CPU_DIR" ]; then
            # 获取硬件最大频率
            if [ -f "${CPU_DIR}/cpuinfo_max_freq" ]; then
                HW_MAX_FREQ=$(cat ${CPU_DIR}/cpuinfo_max_freq)
            else
                log_message "WARNING" "无法获取CPU $i 的最大频率信息"
                continue
            fi
            
            # 获取当前设置的最大频率
            if [ -f "${CPU_DIR}/scaling_max_freq" ]; then
                CURRENT_MAX=$(cat ${CPU_DIR}/scaling_max_freq)
                CURRENT_MAX_PERCENT=$(( CURRENT_MAX * 100 / HW_MAX_FREQ ))
            else
                log_message "WARNING" "无法获取CPU $i 的当前最大频率设置"
                continue
            fi
            
            # 计算目标频率
            if [ "$HW_MAX_FREQ" -gt 0 ] && [ "$target_percent" -ge 0 ] && [ "$target_percent" -le 100 ]; then
                TARGET_FREQ=$(( HW_MAX_FREQ * target_percent / 100 ))
            else
                log_message "ERROR" "无效的频率参数: HW_MAX_FREQ=$HW_MAX_FREQ, target_percent=$target_percent"
                continue
            fi
            
            # 如果当前设置已经是目标值，则跳过
            if [ "$CURRENT_MAX" -eq "$TARGET_FREQ" ]; then
                log_message "INFO" "CPU $i 频率已经是 ${target_percent}% ($TARGET_FREQ Hz)，无需调整"
                continue
            fi
            
            log_message "INFO" "CPU $i: 当前最大频率 ${CURRENT_MAX_PERCENT}% ($CURRENT_MAX Hz) -> 目标 ${target_percent}% ($TARGET_FREQ Hz)"
            
            # 设置最大频率
            echo $TARGET_FREQ > ${CPU_DIR}/scaling_max_freq 2>/dev/null
            SET_RESULT=$?
            
            # 验证设置
            if [ -f "${CPU_DIR}/scaling_max_freq" ]; then
                NEW_MAX=$(cat ${CPU_DIR}/scaling_max_freq)
                NEW_MAX_PERCENT=$(( NEW_MAX * 100 / HW_MAX_FREQ ))
                if [ "$SET_RESULT" -eq 0 ] && [ "$NEW_MAX" -eq "$TARGET_FREQ" ]; then
                    log_message "SUCCESS" "CPU $i 频率设置成功: ${CURRENT_MAX_PERCENT}% -> ${NEW_MAX_PERCENT}% ($NEW_MAX Hz)"
                else
                    log_message "ERROR" "CPU $i 频率设置失败: 期望 ${target_percent}% ($TARGET_FREQ Hz)，实际 ${NEW_MAX_PERCENT}% ($NEW_MAX Hz)，命令返回值: $SET_RESULT"
                fi
            else
                log_message "ERROR" "无法访问 ${CPU_DIR}/scaling_max_freq"
            fi
        else
            log_message "WARNING" "CPU $i 不支持频率调节"
        fi
    done
}

# 调整CPU频率
adjust_cpu_frequency() {
    local freq=$1
    local current_time=$(date +%s)
    
    # 确保变量有默认值
    HIGH_FREQ_START=${HIGH_FREQ_START:-0}
    LOW_FREQ_START=${LOW_FREQ_START:-0}
    
    get_current_cpu_freq
    
    # 确保freq是有效数字
    if ! [[ "$freq" =~ ^[0-9]+$ ]]; then
        log_message "WARNING" "无效的CPU频率值: $freq"
        return
    fi
    
    # 判断当前频率状态
    if [ "$freq" -ge "$HIGH_FREQ_THRESHOLD" ]; then
        # 高频率状态
        if [ "$HIGH_FREQ_START" -eq 0 ]; then
            HIGH_FREQ_START=$current_time
            log_message "INFO" "检测到高CPU最大频率 ($freq%)，开始计时"
        elif [ $((current_time - HIGH_FREQ_START)) -ge "$SUSTAINED_PERIOD_HIGH" ]; then
            # 持续高频率，降低频率
            # 检查当前最大频率设置是否已经等于目标频率
            if [ "$CURRENT_PERCENT" -ne "$TARGET_FREQ_AFTER_REDUCTION" ]; then
                log_message "WARNING" "持续高CPU频率，降低CPU频率从${CURRENT_PERCENT}%到${TARGET_FREQ_AFTER_REDUCTION}%"
                set_cpu_max_freq $TARGET_FREQ_AFTER_REDUCTION
                CURRENT_STATE="high_sustained"
            else
                log_message "INFO" "CPU频率已经设置为${TARGET_FREQ_AFTER_REDUCTION}%，无需重复降频"
            fi
        fi
        # 重置低频率计时
        LOW_FREQ_START=0
    elif [[ "$freq" =~ ^[0-9]+$ && "$LOW_FREQ_THRESHOLD" =~ ^[0-9]+$ && "$freq" -le "$LOW_FREQ_THRESHOLD" ]]; then
        # 低频率状态
        if [ "$LOW_FREQ_START" -eq 0 ]; then
            LOW_FREQ_START=$current_time
            log_message "INFO" "检测到低CPU最大频率 ($freq%)，开始计时"
        elif [ $((current_time - LOW_FREQ_START)) -ge "$SUSTAINED_PERIOD_LOW" ]; then
            # 持续低频率，恢复频率
            # 不再检查状态，只要持续时间达到就升频
            local new_percent=$((CURRENT_PERCENT + FREQ_INCREASE))
            if [ "$new_percent" -gt 100 ]; then
                new_percent=100
            fi
            
            # 只有当当前频率不是目标频率时才执行恢复操作
            if [ "$CURRENT_PERCENT" -ne "$new_percent" ]; then
                log_message "SUCCESS" "持续低CPU频率，恢复CPU频率从${CURRENT_PERCENT}%到${new_percent}%"
                set_cpu_max_freq $new_percent
            else
                log_message "INFO" "CPU频率已经设置为${new_percent}%，无需重复调整"
            fi
            CURRENT_STATE="low_sustained"
        fi
        # 重置高频率计时
        HIGH_FREQ_START=0
    else
        # 正常频率范围
        # 检查是否需要重置计时器并记录日志
        if [ "$HIGH_FREQ_START" -ne 0 ] || [ "$LOW_FREQ_START" -ne 0 ]; then
            log_message "INFO" "CPU最大频率恢复正常 ($freq%)，重置计时器"
        fi
        
        # 重置所有计时器
        HIGH_FREQ_START=0
        LOW_FREQ_START=0
        
        # 在正常频率范围内，重置状态
        CURRENT_STATE="normal"
    fi
}

# 系统健康检查
check_system_health() {
    local load=$(get_system_load)
    local io_load=$(get_io_load)
    local max_util=0
    
    # 解析IO负载数据，获取最高使用率
    if [ -n "$io_load" ]; then
        IFS=';' read -ra io_devices <<< "$io_load"
        for io_device in "${io_devices[@]}"; do
            # 跳过空的或无效的设备信息
            if [ -z "$io_device" ] || [[ "$io_device" != *"="* ]] || [[ "$io_device" == *"read_speed_kbs="* ]] || [[ "$io_device" == *"write_speed_kbs="* ]]; then
                continue
            fi
            
            # 解析设备信息
            local device_type=$(echo "$io_device" | cut -d':' -f1)
            local device_name=$(echo "$io_device" | cut -d':' -f2)
            
            # 检查是否是有效的设备信息行
            if [[ "$device_type" == "Unknown" && "$device_name" == *"="* ]]; then
                continue
            fi
            
            local util=$(echo "$io_device" | grep -o 'util=[0-9.]*' | cut -d'=' -f2)
            if [[ -n "$util" && "$util" =~ ^[0-9.]+$ ]]; then
                # 取整数部分进行比较
                util=$(echo "$util" | awk '{print int($1)}')
                if [ "$util" -gt "$max_util" ]; then
                    max_util=$util
                fi
            fi
        done
    fi
    
    # 如果系统负载超过CPU核心数2倍且任何设备IO使用率超过90%，认为系统不健康
    # 注意: load是基于CPU核心数的百分比，所以100%表示满负载
    if [[ "$load" =~ ^[0-9]+$ ]] && [ "$load" -gt 200 ] && [ "$max_util" -gt 90 ]; then
        log_message "CRITICAL" "系统健康状态异常: 系统负载过高($load%)且检测到设备IO使用率峰值($max_util%)"
        return 1
    # 如果只有系统负载过高
    elif [[ "$load" =~ ^[0-9]+$ ]] && [ "$load" -gt 200 ]; then
        log_message "WARNING" "检测到系统负载过高($load%)，但IO使用率正常(最高${max_util}%)"
        # 当系统负载过高时，也应该触发降频措施
        return 3
    # 如果只有IO使用率过高
    elif [ "$max_util" -gt 95 ]; then
        log_message "WARNING" "检测到设备IO使用率峰值($max_util%)，但系统负载正常(${load:-0}%)"
        # 当IO使用率过高时，也应该触发降频措施
        return 4
    fi
    
    return 0
}

# 主监控循环
monitor_loop() {
    log_message "INFO" "CPU调度优化服务已启动"
    log_message "INFO" "检查间隔: ${CHECK_INTERVAL}秒"
    log_message "INFO" "高频率阈值: ${HIGH_FREQ_THRESHOLD}%，持续时间: ${SUSTAINED_PERIOD_HIGH}秒"
    log_message "INFO" "低频率阈值: ${LOW_FREQ_THRESHOLD}%，持续时间: ${SUSTAINED_PERIOD_LOW}秒"
    log_message "INFO" "频率调整幅度: 降低${FREQ_REDUCTION}%，增加${FREQ_INCREASE}%"
    
    # IO负载状态变量
    local io_high_start=0
    local io_high_duration=0
    local last_health_check=0
    
    while true; do
        local freq=$(get_cpu_frequency)
        local io_load=$(get_io_load)
        local current_time=$(date +%s)
        
        # 在每次检测时添加时间分隔符（如果距离上次记录超过1秒）
        if [ $((current_time - LAST_LOG_TIME)) -ge 1 ]; then
            LAST_LOG_TIME=$current_time
            echo -e "---------- $(date "+%Y-%m-%d %H:%M:%S") ----------" >> "$LOG_FILE"
            if [[ $SERVICE_MODE -ne 1 ]]; then
                echo -e "${BLUE}---------- $(date "+%Y-%m-%d %H:%M:%S") ----------${NC}"
            fi
        fi
        
        # 记录CPU信息分隔符
        log_message "INFO" "======= CPU信息 ======="
        log_message "INFO" "当前CPU最大频率: ${freq}%"
        
        # 确保freq是有效数字
        if ! [[ "$freq" =~ ^[0-9]+$ ]]; then
            log_message "WARNING" "无法获取有效的CPU频率值（返回: '$freq'），将跳过本次检测"
            sleep "$CHECK_INTERVAL"
            continue
        fi
        
        # 每30秒执行一次系统健康检查
        if [[ "$last_health_check" =~ ^[0-9]+$ ]] && [ $((current_time - last_health_check)) -ge 30 ]; then
            check_system_health
            health_result=$?
            if [ "$health_result" -eq 1 ]; then
                # 系统不健康时，采取紧急措施
                log_message "CRITICAL" "系统健康状态异常，执行紧急降频到40%"
                set_cpu_max_freq 40
                CURRENT_STATE="emergency"
                sleep 10  # 紧急状态下延长检查间隔
                continue
            elif [ "$health_result" -eq 2 ]; then
                # 只有IO负载高，已经在IO处理部分进行降频，这里只需要记录
                log_message "INFO" "系统健康检查: 检测到高IO负载但系统整体健康状态尚可"
            elif [ "$health_result" -eq 3 ]; then
                # 系统负载过高，需要降频
                log_message "WARNING" "系统负载过高，执行降频措施到60%"
                set_cpu_max_freq 60
                CURRENT_STATE="high_load"
            elif [ "$health_result" -eq 4 ]; then
                # IO使用率过高，需要降频
                log_message "WARNING" "IO使用率过高，执行降频措施到70%"
                set_cpu_max_freq 70
                CURRENT_STATE="high_io_util"
            fi
            last_health_check=$current_time
        fi
        
        # 处理高IO负载情况
        if [ -n "$io_load" ]; then
            # 记录IO信息分隔符
            log_message "INFO" "======= IO信息 ======="
            
            # 解析IO负载数据
            IFS=';' read -ra io_devices <<< "$io_load"
            local io_logged=false
            for io_device in "${io_devices[@]}"; do
                # 跳过空的或无效的设备信息
                if [ -z "$io_device" ] || [[ "$io_device" != *"="* ]]; then
                    # 检查是否是读写速度信息
                    if [[ "$io_device" == *"read_speed_kbs="* ]] || [[ "$io_device" == *"write_speed_kbs="* ]]; then
                        # 这是读写速度信息，用于日志显示
                        if [[ "$io_device" == *"read_speed_kbs="* ]]; then
                            local read_speed_kbs=$(echo "$io_device" | cut -d'=' -f2)
                            if [ "$io_logged" = false ]; then
                                log_message "INFO" "当前无活跃IO设备"
                            fi
                            log_message "INFO" "总读取速度: ${read_speed_kbs} KB/s"
                        elif [[ "$io_device" == *"write_speed_kbs="* ]]; then
                            local write_speed_kbs=$(echo "$io_device" | cut -d'=' -f2)
                            log_message "INFO" "总写入速度: ${write_speed_kbs} KB/s"
                        fi
                    fi
                    continue
                fi
                
                # 解析设备信息
                local device_type=$(echo "$io_device" | cut -d':' -f1)
                local device_name=$(echo "$io_device" | cut -d':' -f2)
                
                # 检查是否是有效的设备信息行
                if [[ "$device_type" == "Unknown" && "$device_name" == *"="* ]]; then
                    continue
                fi
                
                local util=$(echo "$io_device" | grep -o 'util=[0-9.]*' | cut -d'=' -f2)
                local rkB=$(echo "$io_device" | grep -o 'rkB=[0-9.]*' | cut -d'=' -f2)
                local wkB=$(echo "$io_device" | grep -o 'wkB=[0-9.]*' | cut -d'=' -f2)
                local r_await=$(echo "$io_device" | grep -o 'r_await=[0-9.]*' | cut -d'=' -f2)
                local w_await=$(echo "$io_device" | grep -o 'w_await=[0-9.]*' | cut -d'=' -f2)
                
                # 过滤无效设备数据
                if [[ "$device_name" != "Device" && -n "$util" && "$util" =~ ^[0-9.]+$ ]]; then
                    # 只有当IO使用率大于0时才记录设备信息
                    if [ "$(echo "$util > 0" | bc 2>/dev/null || echo 0)" -eq 1 ]; then
                        # 记录详细IO信息
                        log_message "INFO" "${device_name} (${device_type}):"
                        log_message "INFO" "  读: ${rkB:-0} kB/s, 延迟: ${r_await:-0}ms"
                        log_message "INFO" "  写: ${wkB:-0} kB/s, 延迟: ${w_await:-0}ms"
                        log_message "INFO" "  使用率: ${util}%"
                        io_logged=true
                    fi
                else
                    # 跳过无效的设备信息
                    continue
                fi
                
                # 根据设备类型设置不同的阈值(调整为1/5)
                local io_threshold=$IO_HIGH_THRESHOLD
                local rkb_threshold=10000  # SATA 4K读阈值(10MB/s)
                local wkb_threshold=8000   # SATA 4K写阈值(8MB/s)
                if [ "$device_type" = "NVMe" ]; then
                    io_threshold=85  # NVMe设备可以承受更高的IO负载
                    rkb_threshold=40000  # NVMe 4K读阈值(40MB/s)
                    wkb_threshold=36000  # NVMe 4K写阈值(36MB/s)
                fi
                
                # 检查是否超过阈值(使用率或4K读写)
                # 添加对空值和非数字值的检查，防止bc命令报错
                local util_check=0
                local rkb_check=0
                local wkb_check=0
                
                if [[ -n "$util" && -n "$io_threshold" && "$util" =~ ^[0-9.]+$ && "$io_threshold" =~ ^[0-9]+$ ]]; then
                    util_check=$(echo "$util > $io_threshold" | bc 2>/dev/null || echo 0)
                fi
                
                if [[ -n "$rkB" && -n "$rkb_threshold" && "$rkB" =~ ^[0-9.]+$ && "$rkb_threshold" =~ ^[0-9]+$ ]]; then
                    rkb_check=$(echo "$rkB > $rkb_threshold" | bc 2>/dev/null || echo 0)
                fi
                
                if [[ -n "$wkB" && -n "$wkb_threshold" && "$wkB" =~ ^[0-9.]+$ && "$wkb_threshold" =~ ^[0-9]+$ ]]; then
                    wkb_check=$(echo "$wkB > $wkb_threshold" | bc 2>/dev/null || echo 0)
                fi
                
                if [ "$util_check" -eq 1 ] || [ "$rkb_check" -eq 1 ] || [ "$wkb_check" -eq 1 ]; then
                    if [ "$io_high_start" -eq 0 ]; then
                        io_high_start=$current_time
                        # 记录触发原因
                        local trigger_reason=""
                        local util_reason_check=0
                        local rkb_reason_check=0
                        local wkb_reason_check=0
                        
                        if [[ -n "$util" && -n "$io_threshold" && "$util" =~ ^[0-9.]+$ && "$io_threshold" =~ ^[0-9]+$ ]]; then
                            util_reason_check=$(echo "$util > $io_threshold" | bc 2>/dev/null || echo 0)
                        fi
                        
                        if [[ -n "$rkB" && -n "$rkb_threshold" && "$rkB" =~ ^[0-9.]+$ && "$rkb_threshold" =~ ^[0-9]+$ ]]; then
                            rkb_reason_check=$(echo "$rkB > $rkb_threshold" | bc 2>/dev/null || echo 0)
                        fi
                        
                        if [[ -n "$wkB" && -n "$wkb_threshold" && "$wkB" =~ ^[0-9.]+$ && "$wkb_threshold" =~ ^[0-9]+$ ]]; then
                            wkb_reason_check=$(echo "$wkB > $wkb_threshold" | bc 2>/dev/null || echo 0)
                        fi
                        
                        if [ "$util_reason_check" -eq 1 ]; then
                            trigger_reason="使用率 ${util}% > ${io_threshold}%"
                        fi
                        if [ "$rkb_reason_check" -eq 1 ]; then
                            [ -n "$trigger_reason" ] && trigger_reason+=", "
                            trigger_reason+="读 ${rkB} kB/s > ${rkb_threshold} kB/s"
                        fi
                        if [ "$wkb_reason_check" -eq 1 ]; then
                            [ -n "$trigger_reason" ] && trigger_reason+=", "
                            trigger_reason+="写 ${wkB} kB/s > ${wkb_threshold} kB/s"
                        fi
                        log_message "WARNING" "检测到高IO负载(${device_name}: ${trigger_reason})，开始计时"
                    else
                        io_high_duration=$((current_time - io_high_start))
                        
                        # 根据IO负载严重程度动态调整CPU频率
                        local util_critical_check=0
                        local util_severe_check=0
                        
                        if [[ -n "$util" && -n "$IO_CRITICAL_THRESHOLD" && "$util" =~ ^[0-9.]+$ && "$IO_CRITICAL_THRESHOLD" =~ ^[0-9]+$ ]]; then
                            util_critical_check=$(echo "$util > $IO_CRITICAL_THRESHOLD" | bc 2>/dev/null || echo 0)
                        fi
                        
                        if [[ -n "$util" && -n "$IO_SEVERE_THRESHOLD" && "$util" =~ ^[0-9.]+$ && "$IO_SEVERE_THRESHOLD" =~ ^[0-9]+$ ]]; then
                            util_severe_check=$(echo "$util > $IO_SEVERE_THRESHOLD" | bc 2>/dev/null || echo 0)
                        fi
                        
                        if [ "$util_critical_check" -eq 1 ]; then
                            # 极端IO负载，立即降频到最低安全值
                            log_message "CRITICAL" "检测到极端IO负载(${device_name}: ${util}%)，立即降频到50%"
                            set_cpu_max_freq 50
                            CURRENT_STATE="critical_io"
                        elif [ "$util_severe_check" -eq 1 ] && [ "$io_high_duration" -gt 5 ]; then
                            # 严重IO负载持续5秒，降频到60%
                            log_message "WARNING" "严重IO负载(${device_name}: ${util}%)持续${io_high_duration}秒，降频到60%"
                            set_cpu_max_freq 60
                            CURRENT_STATE="severe_io"
                        elif [ "$io_high_duration" -gt 10 ]; then
                            # 一般高IO负载持续10秒，降频到75%
                            log_message "WARNING" "高IO负载(${device_name}: ${util}%)持续${io_high_duration}秒，降频到75%"
                            set_cpu_max_freq 75
                            CURRENT_STATE="high_io"
                        fi
                    fi
                fi
            done
            
            # 如果没有记录任何IO信息，则添加提示
            if [ "$io_logged" = false ]; then
                log_message "INFO" "当前无活跃IO设备"
            fi
            
            # 添加CPU频率调整调用，确保即使在IO负载处理后也能调整CPU频率
            adjust_cpu_frequency $freq
        else
            # IO负载正常时，重置IO计时器并恢复CPU频率调整
            if [ "$io_high_start" -ne 0 ]; then
                log_message "INFO" "IO负载恢复正常(${io_load}%)，重置计时器"
                io_high_start=0
                io_high_duration=0
            fi
            adjust_cpu_frequency $freq
        fi
        
        sleep "$CHECK_INTERVAL"
    done
}

# 创建系统服务
create_service() {
    local service_file="/etc/systemd/system/cpu-scheduler.service"
    local script_dir=$(dirname "$(readlink -f "$0")")
    local script_path=$(readlink -f "$0")
    
    cat > "$service_file" << EOF
[Unit]
Description=CPU Scheduler Service
After=network.target

[Service]
Type=simple
ExecStart=/bin/bash "$script_path" \\
    --service \\
    -i "$CHECK_INTERVAL" \\
    -h "$HIGH_FREQ_THRESHOLD" \\
    -l "$LOW_FREQ_THRESHOLD" \\
    -s "$SUSTAINED_PERIOD_HIGH" \\
    --sustained-low "$SUSTAINED_PERIOD_LOW" \\
    -r "$FREQ_REDUCTION" \\
    -n "$FREQ_INCREASE" \\
    -f "$LOG_FILE"
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF
    
    systemctl daemon-reload
    systemctl enable cpu-scheduler.service
    
    log_message "SUCCESS" "CPU调度优化服务已创建"
    echo -e "${GREEN}CPU调度优化服务已创建${NC}"
    echo "使用以下命令管理服务:"
    echo "  启动服务: systemctl start cpu-scheduler.service"
    echo "  查看状态: systemctl status cpu-scheduler.service"
    echo "  停止服务: systemctl stop cpu-scheduler.service"
    echo "  禁用服务: systemctl disable cpu-scheduler.service"
    echo "  查看日志: journalctl -u cpu-scheduler.service"
}

# 主程序入口
main() {
    # 记录脚本启动
    log_message "INFO" "CPU调度优化脚本启动"
    
    # 检查是否以root权限运行
    if [ "$EUID" -ne 0 ]; then
        log_message "ERROR" "此脚本需要root权限运行"
        exit 1
    fi
    
    # 加载配置文件（如果存在）
    load_config
    
    # 获取CPU信息和初始化变量
    get_cpu_info
    
    # 创建日志目录
    mkdir -p $(dirname "$LOG_FILE")
    
    # 如果不是服务模式，询问是否安装为系统服务
    if [[ $SERVICE_MODE -ne 1 ]]; then
        echo -e "${BLUE}===== CPU调度优化脚本 =====${NC}"
        echo "检查间隔: ${CHECK_INTERVAL}秒"
        echo "高频率阈值: ${HIGH_FREQ_THRESHOLD}%，持续时间: ${SUSTAINED_PERIOD_HIGH}秒"
        echo "低频率阈值: ${LOW_FREQ_THRESHOLD}%，持续时间: ${SUSTAINED_PERIOD_LOW}秒"
        echo "频率调整幅度: 降低${FREQ_REDUCTION}%，增加${FREQ_INCREASE}%"
        echo "日志文件: ${LOG_FILE}"
        echo
        
        read -p "是否将CPU调度优化安装为系统服务? (y/n): " -n 1 -r
        echo
        if [[ $REPLY =~ ^[Yy]$ ]]; then
            create_service
            exit 0
        fi
    fi
    
    # 运行监控循环
    if [[ $SERVICE_MODE -eq 1 ]]; then
        log_message "INFO" "CPU调度优化服务已在后台启动"
        # 在服务模式下，确保循环不会意外退出
        while true; do
            monitor_loop
            sleep 1
        done
    else
        echo -e "${BLUE}===== CPU调度优化监控 =====${NC}"
        echo "按 Ctrl+C 停止监控"
        echo
        monitor_loop
    fi
}

# 脚本入口
main
